package io.github.echarts.model.theme.provider;

import io.github.echarts.model.context.ConfigurationContext;
import io.github.echarts.model.theme.AbstractDefaultValueProvider;
import io.github.echarts.model.theme.Theme;
import io.github.echarts.option.component.Grid;

/**
 * 网格默认值提供者
 * <p>
 * 为网格组件提供默认配置，包括位置、大小和样式。
 * 网格是笛卡尔坐标系的容器，其定位和尺寸直接影响坐标系的布局。
 * </p>
 */
public class GridDefaultValueProvider extends AbstractDefaultValueProvider<Grid> {
    
    /**
     * 构造函数
     */
    public GridDefaultValueProvider() {
        super(Grid.class);
    }
    
    @Override
    protected void initDefaultValues() {
        // 基本属性
        registerDefaultValue("show", false);  // 默认不显示网格边框
        registerDefaultValue("containLabel", true);  // 默认包含坐标轴标签
        registerDefaultValue("zlevel", 0);    // 0层级
        registerDefaultValue("z", 2);         // 默认置于2层
    }
    
    @Override
    public void applyDefaults(Grid grid, ConfigurationContext context) {
        super.applyDefaults(grid, context);
        
        // 根据上下文信息设置网格边距
        // 对于不同类型的图表，网格边距可能有所不同
        String chartType = getChartType(context);
        
        if (chartType != null) {
            applyChartTypeSpecificDefaults(grid, chartType, context);
        } else {
            // 应用通用边距
            applyDefaultMargins(grid);
        }
        
        // 检查是否需要显示网格边框
        Boolean showBorder = shouldShowBorder(context);
        if (Boolean.TRUE.equals(showBorder) && grid.getShow() == null) {
            grid.setShow(true);
            
            // 设置边框颜色
            if (grid.getBorderColor() == null) {
                grid.setBorderColor("#e0e0e0");  // 浅灰色边框
            }
            
            // 设置边框宽度
            if (grid.getBorderWidth() == null) {
                grid.setBorderWidth(1);
            }
        }
    }
    
    /**
     * 应用默认边距
     * 
     * @param grid 网格对象
     */
    private void applyDefaultMargins(Grid grid) {
        // 只有在未明确设置的情况下应用默认值
        if (grid.getLeft() == null) {
            grid.setLeft("10%");
        }
        
        if (grid.getRight() == null) {
            grid.setRight("10%");
        }
        
        if (grid.getTop() == null) {
            grid.setTop("60");  // 为标题和图例留出空间
        }
        
        if (grid.getBottom() == null) {
            grid.setBottom("10%");
        }
    }
    
    /**
     * 根据图表类型应用特定默认值
     * 
     * @param grid 网格对象
     * @param chartType 图表类型
     * @param context 配置上下文
     */
    private void applyChartTypeSpecificDefaults(Grid grid, String chartType, ConfigurationContext context) {
        switch (chartType.toLowerCase()) {
            case "bar":
                applyBarChartDefaults(grid, context);
                break;
            case "line":
                applyLineChartDefaults(grid, context);
                break;
            case "scatter":
                applyScatterChartDefaults(grid, context);
                break;
            case "heatmap":
                applyHeatmapDefaults(grid, context);
                break;
            default:
                applyDefaultMargins(grid);
                break;
        }
    }
    
    /**
     * 为柱状图应用默认网格设置
     * 
     * @param grid 网格对象
     * @param context 配置上下文
     */
    private void applyBarChartDefaults(Grid grid, ConfigurationContext context) {
        // 柱状图通常需要较大的底部边距，以容纳坐标轴标签
        if (grid.getLeft() == null) {
            grid.setLeft("10%");
        }
        
        if (grid.getRight() == null) {
            grid.setRight("10%");
        }
        
        if (grid.getTop() == null) {
            grid.setTop("60");  // 为标题和图例留出空间
        }
        
        if (grid.getBottom() == null) {
            grid.setBottom("15%");  // 底部留出更多空间
        }
        
        // 确保包含标签
        grid.setContainLabel(true);
    }
    
    /**
     * 为折线图应用默认网格设置
     * 
     * @param grid 网格对象
     * @param context 配置上下文
     */
    private void applyLineChartDefaults(Grid grid, ConfigurationContext context) {
        // 折线图通常需要较大的左侧边距，以容纳Y轴标签
        if (grid.getLeft() == null) {
            grid.setLeft("12%");
        }
        
        if (grid.getRight() == null) {
            grid.setRight("8%");
        }
        
        if (grid.getTop() == null) {
            grid.setTop("60");
        }
        
        if (grid.getBottom() == null) {
            grid.setBottom("12%");
        }
        
        // 确保包含标签
        grid.setContainLabel(true);
    }
    
    /**
     * 为散点图应用默认网格设置
     * 
     * @param grid 网格对象
     * @param context 配置上下文
     */
    private void applyScatterChartDefaults(Grid grid, ConfigurationContext context) {
        // 散点图通常需要更多空间来展示点的分布
        if (grid.getLeft() == null) {
            grid.setLeft("10%");
        }
        
        if (grid.getRight() == null) {
            grid.setRight("10%");
        }
        
        if (grid.getTop() == null) {
            grid.setTop("60");
        }
        
        if (grid.getBottom() == null) {
            grid.setBottom("12%");
        }
        
        // 确保包含标签
        grid.setContainLabel(true);
    }
    
    /**
     * 为热力图应用默认网格设置
     * 
     * @param grid 网格对象
     * @param context 配置上下文
     */
    private void applyHeatmapDefaults(Grid grid, ConfigurationContext context) {
        // 热力图通常使用方形网格
        if (grid.getLeft() == null) {
            grid.setLeft("10%");
        }
        
        if (grid.getRight() == null) {
            grid.setRight("12%");  // 为颜色条留出空间
        }
        
        if (grid.getTop() == null) {
            grid.setTop("60");
        }
        
        if (grid.getBottom() == null) {
            grid.setBottom("10%");
        }
        
        // 热力图通常显示网格边框
        if (grid.getShow() == null) {
            grid.setShow(true);
        }
    }
    
    @Override
    protected void applyDataDrivenDefaults(Grid grid, ConfigurationContext context) {
        // 根据数据特征调整网格配置
        
        // 检查轴标签长度，可能需要调整边距
        Boolean hasLongAxisLabels = hasLongAxisLabels(context);
        if (Boolean.TRUE.equals(hasLongAxisLabels)) {
            // 如果有长标签，增加底部和左侧边距
            if (grid.getBottom() == null || "10%".equals(grid.getBottom())) {
                grid.setBottom("15%");
            }
            
            if (grid.getLeft() == null || "10%".equals(grid.getLeft())) {
                grid.setLeft("15%");
            }
        }
    }
    
    @Override
    public void ensureCompleteness(Grid grid, ConfigurationContext context) {
        // 确保网格区域定义完整
        
        // 如果未设置任何边界值，应用默认值
        boolean needsDefaults = grid.getLeft() == null && grid.getRight() == null && 
                                grid.getTop() == null && grid.getBottom() == null;
                                
        if (needsDefaults) {
            applyDefaultMargins(grid);
        }
        
        // 确保containLabel属性设置
        if (grid.getContainLabel() == null) {
            grid.setContainLabel(true);
        }
    }
    
    @Override
    public void applyTheme(Grid grid, Theme theme) {
        if (grid == null || theme == null) {
            return;
        }
        
        // 应用主题中的边框颜色
        if (Boolean.TRUE.equals(grid.getShow()) && grid.getBorderColor() == null) {
            grid.setBorderColor(theme.getSplitLineColor());
        }
        
        // 应用主题中的背景色（如果网格需要显示背景）
        if (Boolean.TRUE.equals(grid.getShow()) && grid.getBackgroundColor() == null) {
            // 背景色通常是主题背景色的轻微变体
            String themeBackgroundColor = theme.getBackgroundColor();
            grid.setBackgroundColor(themeBackgroundColor);
        }
    }
    
    /**
     * 获取图表类型
     * 
     * @param context 配置上下文
     * @return 图表类型
     */
    private String getChartType(ConfigurationContext context) {
        if (context == null) {
            return null;
        }
        
        Object chartTypeObj = context.get("chartType");
        if (chartTypeObj != null) {
            return chartTypeObj.toString();
        }
        
        return null;
    }
    
    /**
     * 判断是否应该显示网格边框
     * 
     * @param context 配置上下文
     * @return 是否显示边框
     */
    private Boolean shouldShowBorder(ConfigurationContext context) {
        if (context == null) {
            return null;
        }
        
        // 检查是否显式要求显示边框
        Object showBorderObj = context.get("showGridBorder");
        if (showBorderObj instanceof Boolean) {
            return (Boolean) showBorderObj;
        }
        
        // 某些图表类型默认显示边框
        String chartType = getChartType(context);
        if (chartType != null) {
            return "heatmap".equalsIgnoreCase(chartType) || 
                   "treemap".equalsIgnoreCase(chartType) || 
                   "table".equalsIgnoreCase(chartType);
        }
        
        return null;
    }
    
    /**
     * 判断是否有长轴标签
     * 
     * @param context 配置上下文
     * @return 是否有长轴标签
     */
    private Boolean hasLongAxisLabels(ConfigurationContext context) {
        if (context == null) {
            return null;
        }
        
        Object hasLongLabelsObj = context.get("hasLongAxisLabels");
        if (hasLongLabelsObj instanceof Boolean) {
            return (Boolean) hasLongLabelsObj;
        }
        
        // 检查最长类目名称
        Object maxCategoryLengthObj = context.get("maxCategoryLength");
        if (maxCategoryLengthObj instanceof Number) {
            int maxLength = ((Number) maxCategoryLengthObj).intValue();
            return maxLength > 8;  // 如果类目名称超过8个字符，认为是长标签
        }
        
        return null;
    }
} 